#include "financialwidget.h"
#include "ui_financialwidget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QChartView>
#include <QLabel>
#include <QComboBox>
#include <QDate>
#include <QDateEdit>
#include <QPushButton>
#include <QTableWidget>
#include <QSqlQuery>
#include <QHeaderView>
#include <QFormLayout>
#include <QLineEdit>
#include <QDialogButtonBox>
#include <QDialog>
#include <QSqlError>
#include <QPieSeries>
#include <QValueAxis>
#include <QLineSeries>
#include <QDateTimeAxis>
#include <QMessageBox>
FinancialWidget::FinancialWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::FinancialWidget)
{
    ui->setupUi(this);
    setupUI();
    populateStudentComboBox();
}

FinancialWidget::~FinancialWidget()
{
    delete ui;
}

void FinancialWidget::setupUI()
{
    // 创建主布局，用于管理整个窗口的布局
    QVBoxLayout* mainLayout = new QVBoxLayout(this);
    // 创建顶部布局，用于管理顶部控件的布局
    QHBoxLayout* topLayout = new QHBoxLayout();
    // 创建中间布局，用于管理中间控件的布局
    QHBoxLayout* middleLayout = new QHBoxLayout();
    // 创建图表视图，用于显示图表
    // QChartView* chartView = new QChartView();
    chartView = new QChartView(this);  // 这是成员变量，赋值正确

    // 将顶部布局添加到主布局中
    mainLayout->addLayout(topLayout);
    // 将中间布局添加到主布局中，并设置其占主布局的60%高度
    mainLayout->addLayout(middleLayout, 60); // 占60%高度
    // 将图表视图添加到主布局中，并设置其占主布局的40%高度
    mainLayout->addWidget(chartView, 40); // 占40%高度

    // 顶部筛选条件与按钮布局
    topLayout->addWidget(new QLabel("学生姓名:", this));
    studentComboBox = new QComboBox(this);
    topLayout->addWidget(studentComboBox);



    topLayout->addWidget(new QLabel("起始日期:", this));// 在顶部布局中添加标签，用于显示“起始日期”文本
    startDateEdit = new QDateEdit(QDate::currentDate().addMonths(-1));// 创建日期编辑控件，选择起始日期，初始日期设置为当前日期的前一个月
    startDateEdit->setCalendarPopup(true);// 启用日期编辑控件的日历弹出功能，允许用户点击控件选择日期
    topLayout->addWidget(startDateEdit);// 将起始日期编辑控件添加到顶部布局中

    topLayout->addWidget(new QLabel("结束日期:", this));// 在顶部布局中添加一个标签，显示“结束日期”文本
    endDateEdit = new QDateEdit(QDate::currentDate());// 创建日期编辑控件，选择结束日期，初始日期设置为当前日期
    endDateEdit->setCalendarPopup(true);// 启用日期编辑控件的日历弹出功能，用户通过点击控件选择日期
    topLayout->addWidget(endDateEdit);// 将结束日期编辑控件添加到顶部布局中

    //添加、修改、删除按钮
    QPushButton* addButton = new QPushButton("添加");
    deleteButton = new QPushButton("删除");
    editButton = new QPushButton("修改");
    topLayout->addWidget(addButton);
    topLayout->addWidget(deleteButton);
    topLayout->addWidget(editButton);
    topLayout->addStretch();

    // 主内容布局
    tableWidget = new QTableWidget();
    tableWidget->setFixedWidth(550);
    tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    tableWidget->setAlternatingRowColors(true);
    QStringList header = QStringList() << "ID" << "学生名字" << "缴费日期" << "金额" << "支付类型" << "备注";
    tableWidget->setColumnCount(header.count());
    tableWidget->setHorizontalHeaderLabels(header);
    tableWidget->setColumnHidden(0, true);
    middleLayout->addWidget(tableWidget);
    pieChartView = new QChartView();
    middleLayout->addWidget(pieChartView);
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->setMinimumHeight(200); // 最小高度保障

    // 连接
    connect(addButton, &QPushButton::clicked, this, &FinancialWidget::addRecord);
    connect(deleteButton, &QPushButton::clicked, this, &FinancialWidget::deleteRecord);
    connect(editButton, &QPushButton::clicked, this, &FinancialWidget::editRecord);
    connect(studentComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &FinancialWidget::loadFinancialRecords);
    connect(startDateEdit, &QDateEdit::dateChanged, this, &FinancialWidget::loadFinancialRecords);
    connect(endDateEdit, &QDateEdit::dateChanged, this, &FinancialWidget::loadFinancialRecords);

}

/*
 * 函数名称：loadFinancialRecords
 * 函数作用：从数据库中加载符合条件的财务记录，并显示在表格中
 * 参数说明：无
 * 返回值  ：无
 */
void FinancialWidget::loadFinancialRecords()
{
    tableWidget->setRowCount(0); // 清空表格中的所有行，防止数据重复

    QString studentId = studentComboBox->currentData().toString(); // 获取当前选中的学生 ID
    QDate startDate = startDateEdit->date(); // 获取起始日期
    QDate endDate = endDateEdit->date(); // 获取结束日期

    // 构建 SQL 查询语句，查询指定时间范围内的缴费记录
    QString queryStr = QString(
                           "SELECT fr.id, s.name, fr.payment_date, fr.amount, fr.payment_type, fr.notes "
                           "FROM financialRecords fr "
                           "JOIN studentInfo s ON fr.student_id = s.id "
                           "WHERE fr.payment_date BETWEEN '%1' AND '%2' %3"
                           ).arg(startDate.toString("yyyy-MM-dd"), // 格式化起始日期
                                endDate.toString("yyyy-MM-dd"), // 格式化结束日期
                                studentId != "-1" ? QString("AND fr.student_id = '%1'").arg(studentId) : ""); // 如果选择了具体学生，则添加筛选条件

    QSqlQuery query(queryStr); // 执行 SQL 查询

    while (query.next()) { // 遍历查询结果
        int row = tableWidget->rowCount(); // 获取当前表格的行数
        tableWidget->insertRow(row); // 插入新的一行

        for (int col = 0; col < 6; ++col) { // 遍历所有列
            QTableWidgetItem* item = new QTableWidgetItem(query.value(col).toString()); // 获取查询结果并创建表格项
            item->setTextAlignment(Qt::AlignCenter); // 设置文本居中对齐
            tableWidget->setItem(row, col, item); // 将项添加到表格的相应位置
        }
    }
    tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter); // 设置表头文本居中对齐

    updateChart();    // 更新下方折线图
    updatePieChart();    // 更新右侧饼图
}



/*
 * 名称：populateStudentComboBox
 * 作用：从数据库中获取所有学生信息，并填充到下拉框中
 */
void FinancialWidget::populateStudentComboBox()
{
    studentComboBox->clear(); // 清空下拉框中的所有选项，避免重复添加

    studentComboBox->addItem("所有学生", QVariant("-1")); // 添加一个默认选项 "所有学生"，对应的值为 "-1"

    QSqlQuery query("SELECT id, name FROM studentInfo"); // 执行 SQL 查询，获取 studentInfo 表中的 id 和 name
    while (query.next()) { // 遍历查询结果集
        QString id = query.value(0).toString(); // 获取当前行的 id，并转换为字符串
        QString name = query.value(1).toString(); // 获取当前行的 name，并转换为字符串
        studentComboBox->addItem(name, QVariant(id)); // 将学生姓名作为选项文本，id 作为对应的数据添加到下拉框
    }
}



/**
 * 添加新的缴费记录
 */
void FinancialWidget::addRecord()
{
    // 创建一个对话框，用于收集用户输入
    QDialog dialog(this);
    dialog.setWindowTitle("添加缴费记录"); // 设置对话框标题为"添加缴费记录"
    QFormLayout form(&dialog); // 创建表单布局，用于管理对话框中的控件布局

    // 学生名称下拉菜单
    QComboBox* studentNameComboBox = new QComboBox(&dialog); // 创建学生名称下拉菜单
    QSqlQuery query("SELECT id, name FROM studentInfo"); // 执行 SQL 查询，从 studentInfo 表中获取学生ID和名称
    while (query.next()) {
        QString id = query.value(0).toString(); // 获取学生ID
        QString name = query.value(1).toString(); // 获取学生名称
        studentNameComboBox->addItem(name, QVariant(id)); // 将学生ID与名称关联
    }
    QDateEdit* paymentDateEdit = new QDateEdit(&dialog); // 创建日期编辑控件，用于选择缴费日期
    paymentDateEdit->setDate(QDate::currentDate()); // 设置默认值为当前日期
    paymentDateEdit->setCalendarPopup(true); // 允许弹出日历选择器
    QLineEdit* amountEdit = new QLineEdit(&dialog); // 创建金额编辑框
    QLineEdit* feeTypeEdit = new QLineEdit(&dialog); // 创建支付类型编辑框
    QLineEdit* remarkEdit = new QLineEdit(&dialog); // 创建备注编辑框

    form.addRow("学生名称:", studentNameComboBox); // 将学生名称下拉菜单添加到表单布局
    form.addRow("缴费日期:", paymentDateEdit); // 将日期编辑框添加到表单布局，修改为 QDateEdit
    form.addRow("金额:", amountEdit); // 将金额编辑框添加到表单布局
    form.addRow("支付类型:", feeTypeEdit); // 将支付类型编辑框添加到表单布局
    form.addRow("备注:", remarkEdit); // 将备注编辑框添加到表单布局

    QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); // 创建按钮布局，包含"确定"和"取消"按钮
    buttonBox.button(QDialogButtonBox::Ok)->setText("确定"); // 设置"确定"按钮文本为"确定"
    buttonBox.button(QDialogButtonBox::Cancel)->setText("取消"); // 设置"取消"按钮文本为"取消"
    form.addRow(&buttonBox); // 将按钮布局添加到表单布局
    connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); // 连接"确定"按钮信号到对话框的 accept 槽
    connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); // 连接"取消"按钮信号到对话框的 reject 槽

    if (dialog.exec() == QDialog::Accepted) {
        QString studentId = studentNameComboBox->currentData().toString();
        QString paymentDate = paymentDateEdit->date().toString("yyyy-MM-dd");
        double amount = amountEdit->text().toDouble();
        QString feeType = feeTypeEdit->text();
        QString remark = remarkEdit->text();

        // 准备SQL查询
        QSqlQuery query;
        query.prepare("INSERT INTO financialRecords (student_id, payment_date, amount, payment_type, notes) "
                      "VALUES (:student_id, :payment_date, :amount, :payment_type, :notes)");
        query.bindValue(":student_id", studentId);  // 绑定学生ID
        query.bindValue(":payment_date", paymentDate);
        query.bindValue(":amount", amount);
        query.bindValue(":payment_type", feeType);
        query.bindValue(":notes", remark);



        // 执行SQL查询
        if (query.exec()) { // 如果执行成功
            qDebug() << "记录添加成功！"; // 输出"记录添加成功！"
            loadFinancialRecords(); // 刷新表格
        } else qDebug() << "添加记录失败: " << query.lastError().text(); // 输出错误信息
    }
}


void FinancialWidget::updatePieChart()
{
    QString studentId = studentComboBox->currentData().toString();
    QDate startDate = startDateEdit->date();
    QDate endDate = endDateEdit->date();

    QString queryStr = QString(
        "SELECT payment_type, SUM(amount) "
        "FROM financialRecords "
        "WHERE payment_date BETWEEN '%1' AND '%2' %3 "
        "GROUP BY payment_type")
            .arg(startDate.toString("yyyy-MM-dd"))
            .arg(endDate.toString("yyyy-MM-dd"))
            .arg(studentId != "-1" ? QString("AND student_id = '%1'").arg(studentId) : "");

    QSqlQuery query(queryStr);

    QPieSeries* series = new QPieSeries();
    //qreal totalAmount = 0;

    while (query.next()) {
        QString type = query.value(0).toString();
        qreal value = query.value(1).toDouble();
        //totalAmount += value;

        if (value > 0) {
            QString legendLabel = QString("%1\n%2元").arg(type).arg(value);
            QPieSlice* slice = new QPieSlice(legendLabel, value);
            slice->setLabelVisible(false);
            series->append(slice);
        }
    }

    QChart* chart = new QChart();
    chart->addSeries(series);
    chart->setTitle("支付类型分布");

    // 图例设置
    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignBottom);
    chart->legend()->setBackgroundVisible(true);
    chart->legend()->setBrush(QBrush(Qt::white));
    chart->legend()->setLabelColor(Qt::black);
    chart->legend()->setContentsMargins(10, 10, 10, 10);

    // 饼图尺寸
    series->setPieSize(0.75);

    if (pieChartView->chart()) {
        delete pieChartView->chart();
    }
    pieChartView->setChart(chart);

    // 强制重绘
    pieChartView->repaint();
}


void FinancialWidget::updateChart()
{
    // =============== 1. 获取并验证日期范围 ===============
    QDate startDate = startDateEdit->date();
    QDate endDate = endDateEdit->date();
    if (startDate > endDate) {
        std::swap(startDate, endDate);
        startDateEdit->setDate(startDate);
        endDateEdit->setDate(endDate);
    }

    // =============== 2. 构建安全SQL查询 ===============
    QString studentId = studentComboBox->currentData().toString();
    QString queryStr = QString("SELECT DATE(payment_date) AS day, SUM(amount) AS total "
                               "FROM financialRecords "
                               "WHERE payment_date BETWEEN :startDate AND :endDate "
                               "%1 GROUP BY day ORDER BY day")
                           .arg(studentId != "-1" ? "AND student_id = :studentId" : "");
    QSqlQuery query;
    query.prepare(queryStr);
    query.bindValue(":startDate", startDate.toString("yyyy-MM-dd"));
    query.bindValue(":endDate", endDate.toString("yyyy-MM-dd"));
    if (!studentId.isEmpty()) query.bindValue(":studentId", studentId);
    if (!query.exec()) qCritical() << "SQL错误" << query.lastError().text();

    // =============== 3. 处理查询数据 ===============
    QMap<QDate, qreal> dayData;
    qreal maxAmount = 0;
    while (query.next()) {
        QDate day = QDate::fromString(query.value(0).toString(), "yyyy-MM-dd");
        if (!day.isValid()) continue;
        qreal amount = query.value(1).toDouble();
        dayData[day] = amount;
        if (amount > maxAmount) maxAmount = amount;
    }

    // =============== 4. 创建图表系列 ===============
    QLineSeries* series = new QLineSeries();
    series->setName("销售额");
    QPen pen(Qt::blue);
    series->setPen(pen);
    QDate currentDate = startDate;
    while (currentDate <= endDate) {
        qreal value = dayData.value(currentDate, 0.0);
        series->append(currentDate.startOfDay().toMSecsSinceEpoch(), value);
        currentDate = currentDate.addDays(1);
    }

    // =============== 5. 配置坐标轴 ===============
    QChart* chart = new QChart();
    chart->addSeries(series);
    QDateTimeAxis* axisX = new QDateTimeAxis();
    axisX->setFormat("yyyy-MM-dd");
    axisX->setTitleText("日期");
    axisX->setRange(startDate.startOfDay(), endDate.startOfDay());
    chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);
    QValueAxis* axisY = new QValueAxis();
    axisY->setTitleText("金额（元）");
    axisY->setLabelFormat("%.0f");
    axisY->setTickCount(10);
    chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisY);

    // =============== 6. 应用图表 ===============
    if (chartView->chart()) delete chartView->chart();
    chartView->setChart(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
    chart->legend()->setVisible(false);
}



void FinancialWidget::editRecord()
{
    // 获取当前选中的行号
    int currentRow = tableWidget->currentRow();
    if (currentRow < 0) {
        QMessageBox::warning(this, "警告", "请选择要修改的记录！");
        return;
    }

    // 获取当前行的每一列数据
    QString id = tableWidget->item(currentRow, 0)->text(); // 记录ID
    QString studentName = tableWidget->item(currentRow, 1)->text(); // 学生姓名
    QString paymentDate = tableWidget->item(currentRow, 2)->text(); // 缴费日期
    QString amount = tableWidget->item(currentRow, 3)->text(); // 缴费金额
    QString feeType = tableWidget->item(currentRow, 4)->text(); // 支付类型
    QString remark = tableWidget->item(currentRow, 5)->text(); // 备注

    // 创建一个对话框用于编辑
    QDialog dialog(this);
    dialog.setWindowTitle("修改缴费记录");
    QFormLayout form(&dialog); // 使用表单布局

    // 创建学生名称下拉框并从 studentInfo 表中读取学生数据
    QComboBox* studentNameComboBox = new QComboBox(&dialog);
    QSqlQuery query("SELECT id, name FROM studentInfo"); // 查询学生ID和姓名
    while (query.next()) {
        QString id = query.value(0).toString(); // 学生ID
        QString name = query.value(1).toString(); // 学生姓名
        studentNameComboBox->addItem(name, QVariant(id)); // 添加到下拉框中，文本为姓名，数据为ID
    }
    studentNameComboBox->setCurrentText(studentName); // 设置当前学生为选中项

    // 创建其他编辑框，并设置初始值
    QLineEdit* paymentDateEdit = new QLineEdit(paymentDate, &dialog);
    QLineEdit* amountEdit = new QLineEdit(amount, &dialog);
    QLineEdit* feeTypeEdit = new QLineEdit(feeType, &dialog);
    QLineEdit* remarkEdit = new QLineEdit(remark, &dialog);

    // 添加各个字段到表单布局中
    form.addRow("学生名称:", studentNameComboBox);
    form.addRow("缴费日期:", paymentDateEdit);
    form.addRow("金额:", amountEdit);
    form.addRow("支付类型:", feeTypeEdit);
    form.addRow("备注:", remarkEdit);

    // 添加确定和取消按钮
    QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
    buttonBox->button(QDialogButtonBox::Ok)->setText("确定");
    buttonBox->button(QDialogButtonBox::Cancel)->setText("取消");
    form.addRow(buttonBox);

    // 连接按钮事件
    QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
    QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);

    // 如果点击“确定”按钮
    if (dialog.exec() == QDialog::Accepted) {
        // 获取修改后的数据
        QString studentId = studentNameComboBox->currentData().toString(); // 获取下拉框中当前选项的 student_id
        QString paymentDate = paymentDateEdit->text();
        double amount = amountEdit->text().toDouble();
        QString feeType = feeTypeEdit->text();
        QString remark = remarkEdit->text();

        // 使用参数绑定方式准备 SQL 更新语句
        QSqlQuery query;
        query.prepare("UPDATE financialRecords SET student_id = :student_id, payment_date = :payment_date, "
                      "amount = :amount, payment_type = :payment_type, notes = :notes WHERE id = :id");

        // 绑定每个参数对应的值
        query.bindValue(":student_id", studentId);
        query.bindValue(":payment_date", paymentDate);
        query.bindValue(":amount", amount);
        query.bindValue(":payment_type", feeType);
        query.bindValue(":notes", remark);
        query.bindValue(":id", id);

        // 执行 SQL 更新语句
        if (query.exec()) {
            qDebug() << "记录修改成功！";
            loadFinancialRecords(); // 刷新表格内容
        } else {
            qDebug() << "修改记录失败：" << query.lastError().text(); // 打印错误信息
        }
    }
}

void FinancialWidget::deleteRecord()
{
    // 获取当前选中的行号
    int currentRow = tableWidget->currentRow();
    if (currentRow < 0) {
        // 没有选中任何行，弹出警告框
        QMessageBox::warning(this, "警告", "请选择要删除的记录！");
        return;
    }

    // 获取选中行的 ID（一般是主键，位于第一列）
    int id = tableWidget->item(currentRow, 0)->text().toInt(); // 将文本转为整数

    // 创建一个确认删除的消息框
    QMessageBox confirmBox(this);
    confirmBox.setWindowTitle("确认删除");
    confirmBox.setText("确定要删除该记录吗？");

    // 添加“确定”和“取消”按钮（中文）
    QPushButton* yesButton = confirmBox.addButton("确定", QMessageBox::YesRole);
    QPushButton* noButton = confirmBox.addButton("取消", QMessageBox::NoRole);

    // 设置默认按钮为“取消”，防止误操作
    confirmBox.setDefaultButton(noButton);

    // 显示确认对话框并等待用户选择
    confirmBox.exec();

    // 判断用户点击的是不是“确定”按钮
    if (confirmBox.clickedButton() == yesButton) {
        // 创建 SQL 查询对象
        QSqlQuery query;
        // 准备 DELETE SQL 语句，使用绑定参数防止 SQL 注入
        query.prepare("DELETE FROM financialRecords WHERE id = :id");
        query.bindValue(":id", id); // 绑定实际的 ID 值

        // 执行删除操作
        if (query.exec()) {
            qDebug() << "记录删除成功！";
            loadFinancialRecords(); // 删除成功后刷新表格显示
        } else {
            // 如果删除失败，输出错误信息
            qDebug() << "删除记录失败：" << query.lastError().text();
            QMessageBox::warning(this, "错误", "删除记录失败！");
        }
    }
}

